﻿using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

namespace CWM.Skinn
{
    public static partial class SkinnContextCommands
    {
        [CtxMenuItem("SkinnedMeshRenderer/Shapes/Invert",
           "creates a new inverted blend-shape.", ContextFlag.Blendshape, ContextRequirements.HasBlendshapes, 001)]
        public static void SkinnedMeshRendererShapeInvert()
        {
            var contexItem = SkinnContext.GetContextItem();
            if (!contexItem) return;
            var context = contexItem.GetComponent<SkinnedMeshRenderer>();
            if (SkinnEx.IsNullOrNotInAScene(context)) { SkinnContext.Finished(); return; }
            if (!context.HasSharedMesh()) { SkinnContext.Finished(); return; }

            var sharedMesh = context.GetSharedMesh();

            var ContextShape0 = SkinnContext.ContextShape0;
            var shapeIndex = sharedMesh.GetBlendShapeIndex(ContextShape0);
            if (shapeIndex < 0) return;

            var mesh = context.GetSharedMesh().Clone() as Mesh;
            var vertexCount = mesh.vertices.Length;
            var shapeName = mesh.GetBlendShapeName(shapeIndex) + "_Inverted";
            var shapesNames = new List<string>(mesh.GetBlendshapeNames());

            var newShapeName = shapeName;
            int n = 0;
            while (shapesNames.Contains(newShapeName))
            {
                n++;
                newShapeName = shapeName + n.ToString();
            }

            for (int i = 0; i < mesh.GetBlendShapeFrameCount(shapeIndex); i++)
            {
                var deltaVertices = new Vector3[vertexCount];
                var deltaNormals = new Vector3[vertexCount];
                var deltaTangents = new Vector3[vertexCount];
                mesh.GetBlendShapeFrameVertices(shapeIndex, i, deltaVertices, deltaNormals, deltaTangents);

                var hasDeltas = !SkinnEx.IsNullOrEmpty(deltaVertices, vertexCount);
                var hasNormals = !SkinnEx.IsNullOrEmpty(deltaNormals, vertexCount);
                var hasTangents = !SkinnEx.IsNullOrEmpty(deltaTangents, vertexCount);

                for (int ii = 0; ii < vertexCount; ii++)
                {
                    if (hasDeltas) deltaVertices[ii] *= -1f;
                    if (hasNormals) deltaNormals[ii] *= -1f;
                    if (hasTangents) deltaTangents[ii] *= -1f;
                }

                mesh.AddBlendShapeFrame(newShapeName, mesh.GetBlendShapeFrameWeight(shapeIndex, i),
                    hasDeltas ? deltaVertices : new Vector3[vertexCount],
                     hasNormals ? deltaNormals : null,
                      hasTangents ? deltaTangents : null
                    );
            }

            SkinnContext.UndoRecord(context, "Invert Shape");
            context.SetSharedMesh(mesh);

            SkinnContext.Finished();
        }

    }
}